Passed
Push — master ( e361b3...d0267f )
by EMP
02:42
created

main.js ➔ adjustLevel   A

Complexity

Conditions 3

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 10
dl 0
loc 14
rs 9.9
c 0
b 0
f 0
1
"use strict";
2
3
sodium.ready.then(function() {
4
5
let isReady = true;
6
7
let vaultPage = -4;
8
const vault = new PostVault(function(ok) {
0 ignored issues
show
Bug introduced by
The variable PostVault seems to be never declared. If this is a global, consider adding a /** global: PostVault */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
9
	if (ok) vaultPage = -3;
10
});
11
12
const ae = new AllEars(function(ok) {
13
	if (!ok) {
14
		document.getElementById("greeting").textContent = "Failed loading All-Ears";
15
		return;
16
	}
17
18
	try {
19
		if (localStorage.greeting) {
20
			document.getElementById("greeting").textContent = localStorage.greeting;
21
			document.getElementById("txt_pg").value = localStorage.greeting;
22
		} else localStorage.greeting = document.getElementById("greeting").textContent;
23
	} catch(e) {
24
		document.getElementById("btn_pg").disabled = true;
25
		document.getElementById("txt_pg").disabled = true;
26
		document.getElementById("txt_pg").className = "ita";
27
		document.getElementById("txt_pg").value = "LocalStorage inaccessible";
28
	}
29
30
	document.getElementById("txt_umk").maxLength = "60";
31
});
32
33
function TabState(cur, max, btnDele, btnUpdt) {
34
	this.cur = cur;
35
	this.max = max;
36
	this.btnDele = btnDele;
37
	this.btnUpdt = btnUpdt;
38
}
39
40
const tabs = [
41
	new TabState(0, 0, false, true), // Inbox
42
	new TabState(0, 0, false, false), // Outbx
43
	new TabState(0, 1, true,  false), // Write
44
	new TabState(0, 2, false, false), // Notes
45
	new TabState(0, 2, false, false) // Tools
46
];
47
48
function MsgInfo(msgId, msgType, msgNum) {
49
	this.id = msgId;
50
	this.type = msgType;
51
	this.num = msgNum;
52
}
53
54
let msgDisplay = new MsgInfo(null, null, null);
55
let showHeaders = false;
56
let rowsPerPage = 0;
57
58
let tab = 0;
59
const TAB_INBOX = 0;
60
const TAB_DRBOX = 1;
61
const TAB_WRITE = 2;
62
const TAB_NOTES = 3;
63
const TAB_TOOLS = 4;
64
65
function errorDialog(err, focusAfter) {
66
	if (typeof(err) !== "number" || err < 1) return;
67
68
	let btnDisable = [];
69
	const buttons = document.querySelectorAll("nav > button");
70
	buttons.forEach(function(btn) {
71
		btnDisable.push(btn.disabled);
72
		btn.disabled = true;
73
	});
74
75
	const errMsg = ae.getErrorMessage(err);
76
77
	const dlg = document.querySelector("dialog");
78
	dlg.children[0].style.height = getComputedStyle(document.querySelector("#main1 > div[class='mid']")).height;
79
	dlg.querySelector("h1").textContent = "ERROR " + ((err >= 400) ? err : ("0x" + err.toString(16).padStart(2, "0").toUpperCase()));
80
	dlg.querySelector("p").textContent = (typeof(errMsg) === "string") ? errMsg : errMsg[1];
81
	dlg.show();
82
83
	document.querySelector("dialog > div").onclick = function() {
84
		buttons.forEach(function(btn, i) {btn.disabled = btnDisable[i];});
85
		dlg.close();
86
		if (focusAfter) focusAfter.focus();
87
	};
88
89
	document.onkeyup = function(event) {
90
		document.onkeyup = null;
91
		event.preventDefault();
92
93
		buttons.forEach(function(btn, i) {btn.disabled = btnDisable[i];});
94
		dlg.close();
95
		if (focusAfter) focusAfter.focus();
96
	};
97
}
98
99
function getCountryFlag(countryCode) {
100
	return (!countryCode || countryCode.length !== 2 || countryCode === "??") ? "❔" : sodium.to_string(new Uint8Array([
101
		240, 159, 135, 166 + countryCode.codePointAt(0) - 65,
102
		240, 159, 135, 166 + countryCode.codePointAt(1) - 65
103
	]));
104
}
105
106
function getClockIcon(d) {
107
	const h24 = d.getUTCHours();
108
	let h12 = (h24 === 0 ? 12 : ((h24 > 12) ? h24 - 12 : h24));
109
110
	const m60 = (d.getUTCMinutes() * 60) + d.getUTCSeconds();
111
	let m30 = 0;
112
	if (m60 <= 900) { // <= 15: round down to this hour
113
		m30 = 0;
114
	} else if (m60 > 900 && m60 < 2700) { // 15..45: round to half-past this hour
115
		m30 = 12;
116
	} else { // >= 45: round up to next hour
117
		h12++;
118
		m30 = 0;
119
	}
120
121
	return String.fromCodePoint((128335 + h12) + m30);
122
}
123
124
function clearDisplay() {
125
	document.getElementById("btn_mnext").disabled = true;
126
	document.getElementById("btn_mprev").disabled = true;
127
	document.getElementById("readmsg_export").hidden = true;
128
129
	const el = document.querySelector("#readmsg_main > img, #readmsg_main > audio, #readmsg_main > video, #readmsg_main > embed, #readmsg_main > iframe");
130
	if (!el) return;
131
	if (el.src) URL.revokeObjectURL(el.src);
132
	el.remove();
133
}
134
135
/*
136
function addMsgFlag(abbr, abbrTitle) {
137
	const parent = document.getElementById("readmsg_flags").children[0];
138
139
	const el = document.createElement("abbr");
140
	el.title = abbrTitle;
141
	el.textContent = abbr;
142
143
	parent.appendChild(document.createTextNode(" "));
144
	parent.appendChild(el);
145
}
146
*/
147
148
function displayFile(isHistory, num, showNext) {
149
	if (num < 0 || num >= ae.getUplMsgCount()) return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
150
151
	const fileType = ae.getUplMsgType(num);
152
	if (!fileType) {
153
		if (isHistory) return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
154
		if (showNext === true) return displayFile(false, num + 1, true);
155
		if (showNext === false) return displayFile(false, num - 1, false);
156
		ae.downloadUplMsg(num); return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
157
	}
158
159
	clearDisplay();
160
	document.querySelector("article").scroll(0, 0);
161
	document.querySelector("article").setAttribute("data-msgid", ae.getUplMsgId(num));
162
163
	document.getElementById("btn_mdele").disabled = false;
164
	document.getElementById("btn_msave").disabled = false;
165
	document.getElementById("btn_reply").disabled = true;
166
167
	document.getElementById("btn_msave").onclick = function() {ae.downloadUplMsg(num);};
168
169
	document.getElementById("readmsg_info").hidden = true;
170
	document.getElementById("readmsg_dkim").hidden = true;
171
	document.querySelector("#readmsg_main > h1").textContent = ae.getUplMsgTitle(num);
172
173
	msgDisplay = new MsgInfo(ae.getUplMsgId(num), "upl", num);
174
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
175
176
	document.getElementById("main2").hidden = false;
177
	document.getElementById("main1").hidden = !window.matchMedia("(min-width: 80em)").matches;
178
179
	document.getElementById("btn_mnext").disabled = (num === ae.getUplMsgCount() - 1);
180
	document.getElementById("btn_mprev").disabled = (num === 0);
181
	document.getElementById("btn_mnext").onclick = function() {displayFile(false, num + 1, true);};
182
	document.getElementById("btn_mprev").onclick = function() {displayFile(false, num - 1, false);};
183
184
	if (fileType === "text") {
185
		document.querySelector("#readmsg_main > pre").hidden = false;
186
		try {
187
			document.querySelector("#readmsg_main > pre").textContent = sodium.to_string(ae.getUplMsgBody(num));
188
		} catch(e) {
189
			document.querySelector("#readmsg_main > pre").textContent = "Failed decoding body: " + e.message;
190
		}
191
		return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
192
	}
193
194
	document.querySelector("#readmsg_main > pre").hidden = true;
195
	let el;
196
197
	switch (fileType) {
198
		case "image": {
199
			el = document.createElement("img");
200
			el.src = URL.createObjectURL(new Blob([ae.getUplMsgBody(num).buffer]));
201
			el.onclick = function() {
202
				if (!document.fullscreen)
203
					this.requestFullscreen();
204
				else
205
					document.exitFullscreen();
206
			};
207
		break;}
208
209
		case "audio":
210
		case "video": {
211
			el = document.createElement(fileType);
212
			el.controls = "controls";
213
			el.src = URL.createObjectURL(new Blob([ae.getUplMsgBody(num).buffer]));
214
		break;}
215
216
		case "pdf": {
217
			el = document.createElement("embed");
218
			el.type = "application/pdf";
219
			el.src = URL.createObjectURL(new Blob([ae.getUplMsgBody(num).buffer], {type: "application/pdf"}));
220
		break;}
221
222
		case "html": {
223
			el = document.createElement("iframe");
224
			el.allow = "vertical-scroll";
225
			el.sandbox = "";
226
			el.referrerPolicy = "no-referrer";
227
228
			try {
229
				const sanBody = document.createElement("body");
230
				sanBody.setHTML(sodium.to_string(ae.getUplMsgBody(num).buffer), {sanitizer: new Sanitizer({
0 ignored issues
show
Bug introduced by
The variable Sanitizer seems to be never declared. If this is a global, consider adding a /** global: Sanitizer */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
231
					"allowElements": [
232
						"a","div","p",
233
						"h1","h2","h3","h4","h5","h6",
234
						"em","strong","b","i","u"
235
					],
236
					"allowAttributes": {
237
						"href": ["*"]
238
					}
239
				})});
240
241
				el.srcdoc =
242
				"<!doctype html><html>" +
243
					"<head>" +
244
						"<style>" +
245
							"html, body {background: #080a08; color: #fff; scrollbar-color: #222 #333;}\n" +
246
							"body {opacity:0.55;}\n" +
247
							"body > *:first-child {margin-top: 0; padding-top: 0;}\n" +
248
							"a {color: #fff;}\n" +
249
							"button, input, select, textarea {background: #000; color: #fff;}\n" +
250
						"</style>" +
251
					"</head>" +
252
					sanBody.outerHTML +
253
				"</html>";
254
			} catch(e) {
255
				el.srcdoc = "<!doctype html><html><head><style>body {background: #080a08; color: #fff; opacity:0.55;} h1 {margin: 0;}</style><body><h1>Error</h1><p>" + e.message + "</p></body></html>";
256
			}
257
		break;}
258
259
		case "svg": {
260
			el = document.createElement("iframe");
261
			el.allow = "";
262
			el.sandbox = "";
263
			el.referrerPolicy = "no-referrer";
264
			el.srcdoc = "<!doctype><html><head><style>body,html,svg {margin: 0; padding: 0; border: 0; height: 100%; width: 100%; display: block; background: #080a08;}</style></head><body>" + sodium.to_string(ae.getUplMsgBody(num).buffer) + "</body></html>";
265
		break;}
266
267
		default: return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
268
	}
269
270
	document.getElementById("readmsg_main").appendChild(el);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
271
}
272
273
function displayMsg(isHistory, isInt, num) {
274
	clearDisplay();
275
	document.getElementById("btn_mdele").disabled = false;
276
277
	document.querySelector("article").scroll(0, 0);
278
	document.querySelector("article").setAttribute("data-msgid", isInt? ae.getIntMsgId(num) : ae.getExtMsgId(num));
279
280
	document.getElementById("btn_msave").disabled = false;
281
	document.getElementById("btn_msave").onclick = function() {displayExport(false, isInt, num);};
282
283
	const ts = isInt? ae.getIntMsgTime(num) : ae.getExtMsgTime(num);
284
285
	if (!isInt || (ae.getIntMsgFrom(num) !== "public" && ae.getIntMsgFrom(num) !== "system")) {
286
		document.getElementById("btn_reply").disabled = false;
287
288
		document.getElementById("btn_reply").onclick = function() {
289
			document.getElementById("write_recv").value = isInt? ae.getIntMsgFrom(num) : ae.getExtMsgReplyAddress(num);
290
			document.getElementById("write_subj").value = isInt? ae.getIntMsgTitle(num) : ae.getExtMsgTitle(num);
291
			if (!document.getElementById("write_subj").value.startsWith("Re:")) document.getElementById("write_subj").value = "Re: " + document.getElementById("write_subj").value;
292
			document.querySelector("#write2_ask > input").value = isInt? ae.getIntMsgAsk(num) : "";
293
294
			document.getElementById("write_recv").readOnly = !isInt;
295
			document.getElementById("write_subj").readOnly = !isInt;
296
			document.getElementById("write_subj").setAttribute("data-replyid", isInt? "" : ae.getExtMsgHdrId(num));
297
298
			tabs[TAB_WRITE].cur = 0;
299
			document.getElementById("btn_write").disabled = false;
300
			document.getElementById("btn_write").click();
301
			document.getElementById("write_body").focus();
302
303
			for (const opt of document.getElementById("write_from").options) {
304
				if (opt.value === (isInt ? ae.getIntMsgTo(num) : ae.getExtMsgEnvTo(num).split("@")[0].toLowerCase())) {
305
					opt.selected = true;
306
				}
307
			}
308
		};
309
	} else {
310
		document.getElementById("btn_reply").disabled = true;
311
	}
312
313
	document.getElementById("readmsg_info").hidden = false;
314
	document.querySelector("#readmsg_main > pre").hidden = false;
315
316
	document.getElementById("readmsg_envto").textContent = isInt ? "" : ae.getExtMsgEnvTo(num);
317
	document.getElementById("readmsg_hdrto").textContent = isInt ? ae.getIntMsgTo(num) : (ae.getExtMsgHdrTo(num));
318
	if(!isInt && ae.getExtMsgDnTo(num)) {
319
		const span = document.createElement("span");
320
		span.className = "sans";
321
		span.textContent = " • " + ae.getExtMsgDnTo(num);
322
		document.getElementById("readmsg_hdrto").appendChild(span);
323
	}
324
325
	const tzOs = new Date().getTimezoneOffset();
326
	const msgDate = new Date((ts * 1000) + (tzOs * -60000));
327
	document.getElementById("readmsg_date").children[0].textContent = getClockIcon(msgDate);
328
	document.getElementById("readmsg_date").children[1].dateTime = new Date(ts * 1000).toISOString();
329
330
	if (isInt) {
331
		document.getElementById("readmsg_dkim").hidden = true;
332
333
		document.querySelector("#readmsg_main > h1").textContent = ae.getIntMsgTitle(num);
334
		document.querySelector("#readmsg_main > pre").textContent = ae.getIntMsgBody(num);
335
336
		document.getElementById("readmsg_date").children[1].textContent = msgDate.toISOString().slice(0, 19).replace("T", " ");
337
338
		document.getElementById("readmsg_ip").style.visibility = "hidden";
339
		document.getElementById("readmsg_rdns").style.visibility = "hidden";
340
		document.getElementById("readmsg_greet").style.visibility = "hidden";
341
		document.getElementById("readmsg_cert").style.visibility = "hidden";
342
		document.getElementById("readmsg_envfrom").style.visibility = "hidden";
343
		document.getElementById("readmsg_envto").style.visibility = "hidden";
344
345
		if (ae.getIntMsgFrom(num) !== "system" && ae.getIntMsgFrom(num) !== "public") {
346
			document.getElementById("readmsg_tls").style.visibility = "visible";
347
			document.getElementById("readmsg_tls").children[0].textContent = ae.getIntMsgAsk(num);
348
		} else document.getElementById("readmsg_tls").style.visibility = "hidden";
349
350
		let symbol = document.createElement("span");
351
		switch(ae.getIntMsgType(num)) {
352
			case "system": symbol.title = "System message"; symbol.textContent = "S"; break;
353
			case "public": symbol.title = "Public announcement"; symbol.textContent = "P"; break;
354
			case "e2ee": symbol.title = "End-to-end encrypted message"; symbol.textContent = "🔒"; break;
355
			case "plain": symbol.title = "Plain message"; symbol.textContent = "-"; break;
356
			default: symbol.title = "Unrecognized type: " + ae.getIntMsgType(num); symbol.textContent = "?";
357
		}
358
359
		document.getElementById("readmsg_hdrfrom").replaceChildren(symbol, document.createTextNode(" " + ae.getIntMsgFrom(num)));
360
	} else {
361
		const headers = document.createElement("p");
362
		headers.textContent = ae.getExtMsgHeaders(num);
363
		headers.className = "mono";
364
		headers.hidden = !showHeaders;
365
366
		const body = document.createElement("p");
367
		body.innerHTML = ae.getExtMsgBody(num, false);
368
369
		document.querySelector("#readmsg_main > pre").replaceChildren(headers, body);
370
371
		const h1 = document.querySelector("#readmsg_main > h1");
372
		h1.textContent = ae.getExtMsgTitle(num);
373
		h1.style.cursor = headers.textContent? "pointer" : "";
374
		h1.onclick = function() {
375
			if (!headers.textContent) return;
376
			showHeaders = !showHeaders;
377
			headers.hidden = !showHeaders;
378
		};
379
380
		let hdrSecs = Math.abs(ae.getExtMsgHdrTime(num));
381
		let hdrTime = "";
382
		if (hdrSecs >= 3600) {
383
			const hdrHours = Math.floor(hdrSecs / 3600);
384
			hdrTime += hdrHours.toString() + "h ";
385
			hdrSecs -= hdrHours * 3600;
386
		}
387
		if (hdrSecs >= 60) {
388
			const hdrMins = Math.floor(hdrSecs / 60);
389
			hdrTime += hdrMins.toString() + "m ";
390
			hdrSecs -= hdrMins * 60;
391
		}
392
		hdrTime += hdrSecs + "s";
393
394
		const hdrTz = (ae.getExtMsgHdrTz(num) >= 0 ? "+" : "-") + Math.floor(Math.abs(ae.getExtMsgHdrTz(num)) / 60).toString().padStart(2, "0") + (Math.abs(ae.getExtMsgHdrTz(num)) % 60).toString().padStart(2, "0");
395
396
		let spans = [document.createElement("span"), document.createElement("span"), document.createElement("span")];
397
		spans[0].textContent = msgDate.toISOString().slice(0, 19).replace("T", " ");
398
		spans[1].className = "sans";
399
		spans[1].textContent = " • ";
400
		spans[2].textContent = hdrTz + " " + ((ae.getExtMsgHdrTime(num) >= 0) ? "+" : "-") + hdrTime;
401
		document.getElementById("readmsg_date").children[1].replaceChildren(...spans);
402
403
		document.getElementById("readmsg_ip").style.visibility = "visible";
404
		document.getElementById("readmsg_rdns").style.visibility = "visible";
405
		document.getElementById("readmsg_greet").style.visibility = "visible";
406
		document.getElementById("readmsg_tls").style.visibility = "visible";
407
		document.getElementById("readmsg_cert").style.visibility = "visible";
408
		document.getElementById("readmsg_envfrom").style.visibility = "visible";
409
		document.getElementById("readmsg_envto").style.visibility = "visible";
410
411
		// DKIM
412
		if (ae.getExtMsgDkimCount(num) > 0) {
413
			document.getElementById("readmsg_dkim").hidden = false;
414
415
			document.querySelectorAll("#readmsg_dkim div").forEach(function(d, i) {
416
				if (i >= ae.getExtMsgDkimCount(num)) {
417
					d.textContent = "";
418
					return;
419
				}
420
				d.textContent = (ae.getExtMsgDkimValidSig(num, i) ? "OK" : "❌") + " " + ae.getExtMsgDkimAlgo(num, i) + " " + ae.getExtMsgDkimHeadHash(num, i) + "/" + ae.getExtMsgDkimBodyHash(num, i) + ": "
421
					+ (ae.getExtMsgDkimIdentity(num, i) ? (ae.getExtMsgDkimIdentity(num, i) + "|") : "") + ae.getExtMsgDkimDomain(num, i) + "|" + ae.getExtMsgDkimSelector(num, i)
422
					+ ((ae.getExtMsgDkimTs(num, i) > 0) ? (" @" + ae.getExtMsgDkimTs(num, i)) : "");
423
			});
424
		} else {
425
			document.getElementById("readmsg_dkim").hidden = true;
426
		}
427
428
		// Left side
429
		document.getElementById("readmsg_country").textContent = getCountryFlag(ae.getExtMsgCcode(num));
430
		document.getElementById("readmsg_country").title = ae.getExtMsgCname(num);
431
		document.getElementById("readmsg_ip").children[1].textContent = ae.getExtMsgIp(num) + (ae.getExtMsgFlagIpBl(num) ? " ❗" : "");
432
		document.getElementById("readmsg_ip").children[2].textContent = " • " + ae.getExtMsgAuSys(num);
433
		document.getElementById("readmsg_tls").children[0].textContent = ae.getExtMsgTLS(num);
434
435
		// Right side
436
		document.getElementById("readmsg_greet").children[0].textContent = ae.getExtMsgGreet(num) + (ae.getExtMsgFlagGrDm(num) ? " ✓" : "");
437
		document.getElementById("readmsg_rdns").children[0].textContent = ae.getExtMsgRdns(num) + (ae.getExtMsgGreet(num).toLowerCase() === ae.getExtMsgRdns(num).toLowerCase() ? " ✓" : "");
438
		document.getElementById("readmsg_cert").children[0].textContent = ae.getExtMsgTlsDomain(num) ? (ae.getExtMsgTlsDomain(num) + " ✓") : "";
439
		document.getElementById("readmsg_envfrom").textContent = ae.getExtMsgEnvFrom(num);
440
		document.getElementById("readmsg_hdrfrom").textContent = ae.getExtMsgHdrFrom(num);
441
		if (ae.getExtMsgDnFrom(num)) {
442
			const span = document.createElement("span");
443
			span.className = "sans";
444
			span.textContent = " • " + ae.getExtMsgDnFrom(num);
445
			document.getElementById("readmsg_hdrfrom").appendChild(span);
446
		}
447
448
/*
449
		clearMsgFlags();
450
		if (!ae.getExtMsgFlagPExt(num)) addMsgFlag("SMTP", "The sender did not use the Extended (ESMTP) protocol");
451
		if ( ae.getExtMsgFlagRare(num)) addMsgFlag("RARE", "The sender issued unusual command(s)");
452
		if ( ae.getExtMsgFlagFail(num)) addMsgFlag("FAIL", "The sender issued invalid command(s)");
453
		if ( ae.getExtMsgFlagPErr(num)) addMsgFlag("PROT", "The sender violated the protocol");
454
*/
455
	}
456
457
	document.getElementById("readmsg_main").hidden = false;
458
	document.getElementById("main2").hidden = false;
459
	document.getElementById("main1").hidden = !window.matchMedia("(min-width: 80em)").matches;
460
461
	msgDisplay = new MsgInfo(isInt? ae.getIntMsgId(num) : ae.getExtMsgId(num), isInt? "int" : "ext", num);
462
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
463
}
464
465
function displayExport(isHistory, isInt, num) {
466
	clearDisplay();
467
	document.getElementById("readmsg_main").hidden = true;
468
	document.getElementById("readmsg_export").hidden = false;
469
	document.getElementById("btn_msave").blur();
470
	document.getElementById("btn_msave").disabled = true;
471
	document.getElementById("btn_reply").disabled = true;
472
	document.getElementById("btn_mdele").disabled = true;
473
474
//	document.querySelector("#readmsg_export > div:nth-child(1)").onclick = function() {};
475
	document.querySelector("#readmsg_export > div:nth-child(2)").onclick = function() {if (isInt) {ae.downloadIntMsg(num);} else {ae.downloadExtMsg(num);} displayMsg(false, isInt, num);};
476
	document.querySelector("#readmsg_export > div:nth-child(3)").onclick = function() {if (isInt) {ae.htmlIntMsg(num, true);} else {ae.htmlExtMsg(num, true);} displayMsg(false, isInt, num);};
477
	document.querySelector("#readmsg_export > div:nth-child(4)").onclick = function() {if (isInt) {ae.txtIntMsg(num, true);} else {ae.txtExtMsg(num, true);} displayMsg(false, isInt, num);};
478
	document.querySelector("#readmsg_export > div:nth-child(5)").onclick = function() {if (isInt) {ae.printIntMsg(num);} else {ae.printExtMsg(num);} displayMsg(false, isInt, num);};
479
	document.querySelector("#readmsg_export > div:nth-child(6)").onclick = function() {navigator.clipboard.writeText(isInt? ae.txtIntMsg(num, false) : ae.txtExtMsg(num, false)); displayMsg(false, isInt, num);};
480
481
	msgDisplay = new MsgInfo(isInt? ae.getIntMsgId(num) : ae.getExtMsgId(num), isInt? "int_exp" : "ext_exp", num);
482
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
483
}
484
485
function displayOutMsg(isHistory, num) {
486
	clearDisplay();
487
	document.querySelector("article").scroll(0, 0);
488
	document.querySelector("article").setAttribute("data-msgid", ae.getOutMsgId(num));
489
490
	document.getElementById("btn_mdele").disabled = false;
491
	document.getElementById("btn_msave").disabled = true;
492
	document.getElementById("btn_reply").disabled = true;
493
494
	document.getElementById("readmsg_info").hidden = false;
495
	document.querySelector("#readmsg_main > pre").hidden = false;
496
497
	document.querySelector("#readmsg_main > h1").textContent = ae.getOutMsgSubj(num);
498
	document.querySelector("#readmsg_main > pre").textContent = ae.getOutMsgBody(num);
499
500
	document.getElementById("readmsg_hdrto").style.visibility   = "visible";
501
	document.getElementById("readmsg_hdrfrom").style.visibility = "visible";
502
	document.getElementById("readmsg_envto").style.visibility   = "visible";
503
504
	document.getElementById("readmsg_hdrfrom").textContent = ae.getOutMsgFrom(num) + "@" + ae.getDomainEml();
505
506
	document.getElementById("readmsg_envto").textContent = ae.getOutMsgMx(num);
507
	document.getElementById("readmsg_hdrto").textContent = ae.getOutMsgTo(num);
508
509
	const ts = ae.getOutMsgTime(num);
510
	const tzOs = new Date().getTimezoneOffset();
511
	document.getElementById("readmsg_date").children[1].textContent = new Date((ts * 1000) + (tzOs * -60000)).toISOString().slice(0, 19).replace("T", " ");
512
513
	const isInt = ae.getOutMsgIsInt(num);
514
	document.getElementById("readmsg_ip").style.visibility    = isInt? "hidden" : "visible";
515
	document.getElementById("readmsg_rdns").style.visibility  = isInt? "hidden" : "visible";
516
	document.getElementById("readmsg_tls").style.visibility   = /*isInt?*/ "hidden" /*: "visible"*/; // TODO
517
	document.getElementById("readmsg_cert").style.visibility  = /*isInt?*/ "hidden" /*: "visible"*/; // TODO
518
	document.getElementById("readmsg_greet").style.visibility = isInt? "hidden" : "visible";
519
	document.getElementById("readmsg_envfrom").style.visibility = isInt? "hidden" : "visible";
520
521
	if (!isInt) {
522
		document.getElementById("readmsg_ip").children[1].textContent = ae.getOutMsgIp(num);
523
		document.getElementById("readmsg_ip").children[2].textContent = " • " + ae.getOutMsgAsn(num);
524
		document.getElementById("readmsg_country").textContent = getCountryFlag(ae.getOutMsgCcode(num));
525
		document.getElementById("readmsg_country").title = ae.getOutMsgCname(num);
526
//		document.getElementById("readmsg_tls").children[0].textContent = ae.getOutMsgTLS(num);
527
		document.getElementById("readmsg_greet").children[0].textContent = ae.getOutMsgGreet(num);
528
		document.getElementById("readmsg_rdns").children[0].textContent = ae.getOutMsgRdns(num);
529
		document.getElementById("readmsg_envfrom").textContent = ae.getOutMsgStatus(num);
530
	}
531
532
//	if ( ae.getOutMsgFlagE2ee(num)) addMsgFlag("E2EE", "End-to-end encrypted");
533
534
	document.getElementById("main2").hidden = false;
535
	document.getElementById("main1").hidden = !window.matchMedia("(min-width: 80em)").matches;
536
537
	msgDisplay = new MsgInfo(ae.getOutMsgId(num), "out", num);
538
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
539
}
540
541
function updateAddressButtons() {
542
	const limitReached = (ae.getAddressCountNormal() + ae.getAddressCountShield() >= 31);
543
	document.getElementById("btn_address_create_normal").disabled = (limitReached || ae.getAddressCountNormal() >= ae.getLimitNormalA(ae.getOwnLevel()));
544
	document.getElementById("btn_address_create_shield").disabled = (limitReached || ae.getAddressCountShield() >= ae.getLimitShieldA(ae.getOwnLevel()));
545
}
546
547
function updateAddressCounts() {
548
	document.querySelector("#tbd_accs > tr > td:nth-child(3)").textContent = ae.getAddressCountNormal();
549
	document.querySelector("#tbd_accs > tr > td:nth-child(4)").textContent = ae.getAddressCountShield();
550
551
	document.getElementById("limit_normal").textContent = (ae.getAddressCountNormal() + "/" + ae.getLimitNormalA(ae.getOwnLevel())).padStart(ae.getLimitNormalA(ae.getOwnLevel()) > 9 ? 5 : 1);
552
	document.getElementById("limit_shield").textContent = (ae.getAddressCountShield() + "/" + ae.getLimitShieldA(ae.getOwnLevel())).padStart(ae.getLimitShieldA(ae.getOwnLevel()) > 9 ? 5 : 1);
553
	document.getElementById("limit_total").textContent = ((ae.getAddressCountNormal() + ae.getAddressCountShield()) + "/" + ae.getAddrPerUser()).padStart(5);
554
555
	updateAddressButtons();
556
//	document.getElementById("getask_result").textContent = ae.getOwnAsk(document.getElementById("getask_addr").value);
557
}
558
559
function addOwnAccount() {
560
	const row = document.getElementById("tbd_accs").insertRow(-1);
561
562
	let cell;
563
	cell = row.insertCell(-1); cell.textContent = ae.uidToName(ae.getOwnUid());
564
	cell = row.insertCell(-1); cell.textContent = Math.round(ae.getTotalMsgBytes() / 1048576); // MiB
565
	cell = row.insertCell(-1); cell.textContent = ae.getAddressCountNormal();
566
	cell = row.insertCell(-1); cell.textContent = ae.getAddressCountShield();
567
568
	cell = row.insertCell(-1);
569
	let btn = document.createElement("button");
570
	btn.type = "button";
571
	btn.textContent = "+";
572
	btn.disabled = true;
573
	cell.appendChild(btn);
574
575
	cell = row.insertCell(-1); cell.textContent = ae.getOwnLevel();
576
577
	cell = row.insertCell(-1);
578
	btn = document.createElement("button");
579
	btn.type = "button";
580
	btn.textContent = "−";
581
	btn.disabled = true;
582
	btn.id = "btn_lowme";
583
	btn.onclick = function() {
584
		const newLevel = parseInt(row.cells[5].textContent, 10) - 1;
585
		ae.Account_Update(ae.getOwnUid(), newLevel, function(error) {
586
			if (error === 0) {
587
				row.cells[5].textContent = newLevel;
588
				if (newLevel === 0) {document.getElementById("btn_lowme").disabled = true;}
589
			} else errorDialog(error);
590
		});
591
	};
592
	cell.appendChild(btn);
593
594
	cell = row.insertCell(-1);
595
	btn = document.createElement("button");
596
	btn.type = "button";
597
	btn.textContent = "X";
598
	btn.disabled = true;
599
	btn.id = "btn_delme";
600
	btn.onclick = function() {
601
		ae.Account_Delete(ae.getOwnUid(), function(error) {
602
			if (error === 0) {
603
				row.remove();
604
				document.getElementById("fs_users").disabled = true;
605
			} else errorDialog(error);
606
		});
607
	};
608
	cell.appendChild(btn);
609
}
610
611
function adjustLevel(uid, level, c) {
612
	const fs = document.getElementById("tbl_accs");
613
	fs.disabled = true;
614
615
	ae.Account_Update(uid, level, function(error) {
616
		fs.disabled = false;
617
618
		if (error === 0) {
619
			c[4].children[0].disabled = (level === 3);
620
			c[5].textContent = level;
621
			c[6].children[0].disabled = (level === 0);
622
		} else errorDialog(error);
623
	});
624
}
625
626
function addMsg(isInt, i) {
627
	const row = document.getElementById("tbl_inbox").insertRow(-1);
628
	row.setAttribute("data-msgid", isInt? ae.getIntMsgId(i) : ae.getExtMsgId(i));
629
630
	const ts = isInt? ae.getIntMsgTime(i) : ae.getExtMsgTime(i);
631
	const el = document.createElement("time");
632
	el.dateTime = new Date(ts * 1000).toISOString();
633
	el.textContent = new Date((ts * 1000) + (new Date().getTimezoneOffset() * -60000)).toISOString().slice(0, 10);
634
	let cell = row.insertCell(-1);
635
	cell.appendChild(el);
636
637
	cell = row.insertCell(-1);
638
	cell.textContent = isInt? ae.getIntMsgTitle(i) : ae.getExtMsgTitle(i);
639
	if (!cell.textContent) cell.textContent = "(fail)";
640
641
	if (isInt) {
642
		cell = row.insertCell(-1);
643
		cell.textContent = ae.getIntMsgFrom(i);
644
		cell.className = (ae.getIntMsgFrom(i).length === 16) ? "mono" : "";
645
	} else {
646
		let from1 = ae.getExtMsgHdrFrom(i);
647
		if (!from1) from1 = ae.getExtMsgEnvFrom(i);
648
		const from2 = from1.substring(from1.indexOf("@") + 1);
649
		cell = row.insertCell(-1);
650
		cell.textContent = from1.substring(0, from1.indexOf("@"));
651
652
		const flag = document.createElement("abbr");
653
		flag.textContent = getCountryFlag(ae.getExtMsgCcode(i));
654
		flag.title = ae.getExtMsgCname(i);
655
656
		const fromText = document.createElement("span");
657
		fromText.textContent = " " + from2;
658
659
		cell = row.insertCell(-1);
660
		cell.appendChild(flag);
661
		cell.appendChild(fromText);
662
	}
663
664
	row.onclick = function() {
665
		displayMsg(false, isInt, i);
666
	};
667
}
668
669
function setRowsPerPage(tbl) {
670
	tbl.replaceChildren();
671
	const row = tbl.insertRow(-1);
672
	const cell = row.insertCell(-1);
673
	cell.textContent = "0";
674
	rowsPerPage = Math.floor(getComputedStyle(tbl).height.replace("px", "") / getComputedStyle(tbl.getElementsByTagName("tr")[0]).height.replace("px", ""));
675
	tbl.replaceChildren();
676
}
677
678
function showInbox() {
679
	const tbl = document.getElementById("tbl_inbox");
680
	if (!document.getElementById("main1").hidden) setRowsPerPage(tbl);
681
682
	const maxExt = ae.getExtMsgCount();
683
	const maxInt = ae.getIntMsgCount();
684
	const loadMore = !ae.haveOldest();
685
686
	if (maxExt + maxInt > 0) {
687
		tabs[TAB_INBOX].max = Math.floor((maxExt + maxInt - (loadMore? 0 : 1)) / rowsPerPage);
688
		document.getElementById("btn_rght").disabled = (tabs[TAB_INBOX].cur >= tabs[TAB_INBOX].max);
689
		tbl.replaceChildren();
690
691
		let skipMsgs = rowsPerPage * tabs[TAB_INBOX].cur;
692
		let numExt = 0;
693
		let numInt = 0;
694
		let numAdd = 0;
695
696
		while (numAdd < rowsPerPage) {
697
			const tsInt = (numInt < maxInt) ? ae.getIntMsgTime(numInt) : -1;
698
			const tsExt = (numExt < maxExt) ? ae.getExtMsgTime(numExt) : -1;
699
			if (tsInt === -1 && tsExt === -1) break;
700
701
			if (tsInt !== -1 && (tsExt === -1 || tsInt > tsExt)) {
702
				if (skipMsgs > 0) skipMsgs--; else {addMsg(true, numInt); numAdd++;}
703
				numInt++;
704
			} else if (tsExt !== -1) {
705
				if (skipMsgs > 0) skipMsgs--; else {addMsg(false, numExt); numAdd++;}
706
				numExt++;
707
			}
708
		}
709
	} else {
710
		tabs[TAB_INBOX].max = 0;
711
	}
712
713
	if (loadMore && tabs[TAB_INBOX].cur >= tabs[TAB_INBOX].max) {
714
		const row = tbl.insertRow(-1);
715
		const cell = row.insertCell(-1);
716
		cell.textContent = "Load more (" + Math.round((ae.getTotalMsgBytes() - ae.getReadyMsgBytes()) / 1024) + " KiB left)";
717
718
		row.onclick = function() {
719
			tbl.style.opacity = 0.5;
720
721
			ae.Message_Browse(false, false, function(errorBrowse) {
722
				tbl.style.opacity = 1;
723
724
				if (errorBrowse !== 0) {
725
					errorDialog(errorBrowse);
726
					return;
727
				}
728
729
				showInbox();
730
			});
731
		};
732
	}
733
}
734
735
function showDrbox() {
736
	const tbl = document.getElementById("tbl_drbox");
737
	if (!document.getElementById("main1").hidden) setRowsPerPage(tbl);
738
739
	const drCount = ae.getOutMsgCount();
740
	const loadMore = ae.getReadyMsgBytes() < ae.getTotalMsgBytes();
741
742
	if (drCount > 0) {
743
		tabs[TAB_DRBOX].max = Math.floor((drCount - (loadMore? 0 : 1)) / rowsPerPage);
744
		document.getElementById("btn_rght").disabled = (tabs[TAB_DRBOX].cur >= tabs[TAB_DRBOX].max);
745
		tbl.replaceChildren();
746
747
		let skipMsgs = rowsPerPage * tabs[TAB_DRBOX].cur;
748
		let numAdd = 0;
749
750
		for (let i = 0; numAdd < rowsPerPage && i < drCount; i++) {
751
			if (skipMsgs > 0) {
752
				skipMsgs--;
753
				continue;
754
			}
755
756
			const row = tbl.insertRow(-1);
757
			row.setAttribute("data-msgid", ae.getOutMsgId(i));
758
759
			let cell;
760
			cell = row.insertCell(-1); cell.textContent = new Date(ae.getOutMsgTime(i) * 1000).toISOString().slice(0, 10);
761
			cell = row.insertCell(-1); cell.textContent = ae.getOutMsgSubj(i);
762
			row.onclick = function() {displayOutMsg(false, i);};
763
764
			numAdd++;
765
		}
766
	} else {
767
		tabs[TAB_DRBOX].max = 0;
768
	}
769
770
	if (loadMore && tabs[TAB_DRBOX].cur >= tabs[TAB_DRBOX].max) {
771
		const row = tbl.insertRow(-1);
772
		const cell = row.insertCell(-1);
773
		cell.textContent = "Load more (" + Math.round((ae.getTotalMsgBytes() - ae.getReadyMsgBytes()) / 1024) + " KiB left)";
774
775
		row.onclick = function() {
776
			tbl.style.opacity = 0.5;
777
778
			ae.Message_Browse(false, false, function(errorBrowse) {
779
				tbl.style.opacity = 1;
780
781
				if (errorBrowse !== 0) {
782
					errorDialog(errorBrowse);
783
					return;
784
				}
785
786
				showDrbox();
787
			});
788
		};
789
	}
790
}
791
792
function showFiles() {
793
	const tbl = document.getElementById("tbl_files");
794
	if (!document.getElementById("main1").hidden) setRowsPerPage(tbl);
795
796
	const msgCount = ae.getUplMsgCount() + ((vaultPage >= 0) ? vault.getTotalFiles() : 0);
797
	const loadMore = ae.getReadyMsgBytes() < ae.getTotalMsgBytes();
798
799
	if (msgCount > 0) {
800
		tabs[TAB_NOTES].max = 2 + Math.floor((msgCount - (loadMore? 0 : 1)) / rowsPerPage);
801
		document.getElementById("btn_rght").disabled = (tabs[TAB_NOTES].cur >= tabs[TAB_NOTES].max);
802
		tbl.replaceChildren();
803
804
		let skipMsgs = rowsPerPage * (tabs[TAB_NOTES].cur - 2);
805
		let numAdd = 0;
806
807
		for (let i = 0; numAdd < rowsPerPage && i < ae.getUplMsgCount(); i++) {
808
			if (skipMsgs > 0) {
809
				skipMsgs--;
810
				continue;
811
			}
812
813
			const row = tbl.insertRow(-1);
814
			row.setAttribute("data-msgid", ae.getUplMsgId(i));
815
			row.className = "rowfile";
816
817
			let cell = row.insertCell(-1);
818
			cell.textContent = new Date(ae.getUplMsgTime(i) * 1000).toISOString().slice(0, 10);
819
			cell.onclick = function() {displayFile(false, i, null);};
820
821
			cell = row.insertCell(-1);
822
			cell.textContent = (ae.getUplMsgBytes(i) / 1024).toFixed(0).padStart(4, " ");
823
			cell.onclick = function() {displayFile(false, i, null);};
824
825
			cell = row.insertCell(-1);
826
			const parentId = ae.getUplMsgParent(i);
827
			if (typeof(parentId) === "number") {
828
				cell.textContent = ae.getExtMsgTitle(parentId);
829
				cell.onclick = function() {displayMsg(false, false, parentId);};
830
			} else if (parentId === false) {
831
				cell.textContent = "Upload";
832
			} else {
833
				cell.textContent = "Unknown";
834
			}
835
836
			cell = row.insertCell(-1);
837
			cell.textContent = ae.getUplMsgTitle(i);
838
			cell.onclick = function() {displayFile(false, i, null);};
839
840
			cell = row.insertCell(-1);
841
			const btn = document.createElement("button");
842
			btn.setAttribute("data-msgid", ae.getUplMsgId(i));
843
			btn.type = "button";
844
			btn.textContent = "X";
845
			btn.onclick = function() {
846
				ae.Message_Delete(this.getAttribute("data-msgid"), function(error) {
847
					if (error === 0) showFiles();
848
					else errorDialog(error);
849
				});
850
			};
851
			cell.appendChild(btn);
852
853
			numAdd++;
854
		}
855
856
		if (vaultPage >= 0) {
857
			for (let i = 0; numAdd < rowsPerPage && i < 256; i++) {
858
				if (vault.getFileSize(i) < 1) continue;
859
860
				if (skipMsgs > 0) {
861
					skipMsgs--;
862
					continue;
863
				}
864
865
				const row = tbl.insertRow(-1);
866
				row.className = "rowfile";
867
868
				let cell = row.insertCell(-1);
869
				cell.textContent = new Date(vault.getFileTime(i) * 1000).toISOString().slice(0, 10);
870
871
				cell = row.insertCell(-1);
872
				cell.textContent = (vault.getFileSize(i) / 1024).toFixed(0).padStart(4, " ");
873
874
				cell = row.insertCell(-1);
875
				cell.textContent = "Vault";
876
877
				cell = row.insertCell(-1);
878
				cell.textContent = vault.getFilePath(i);
879
				cell.onclick = function() {vault.downloadFile(i, function(m,p){}, function(msg) {
0 ignored issues
show
Unused Code introduced by
The parameter p is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter m is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
880
					if (msg !== "Done") errorDialog(404);
881
				});};
882
883
				cell = row.insertCell(-1);
884
				const btn = document.createElement("button");
885
				btn.type = "button";
886
				btn.textContent = "X";
887
				btn.onclick = function() {
888
					vault.deleteFile(i, function(error) {
889
						if (error === 0) showFiles();
890
						else errorDialog(error);
891
					});
892
				};
893
				cell.appendChild(btn);
894
895
				numAdd++;
896
			}
897
		}
898
	} else tabs[TAB_NOTES].max = 2;
899
900
	if (loadMore && tabs[TAB_NOTES].cur >= tabs[TAB_NOTES].max) {
901
		const row = tbl.insertRow(-1);
902
		row.className = "rowfilex";
903
904
		let cell = row.insertCell(-1);
905
		if (ae.getReadyMsgBytes() < ae.getTotalMsgBytes()) {
906
			cell.textContent = "Load more (" + Math.round((ae.getTotalMsgBytes() - ae.getReadyMsgBytes()) / 1024) + " KiB left)";
907
			cell.onclick = function() {
908
				tbl.style.opacity = 0.5;
909
910
				ae.Message_Browse(false, false, function(errorBrowse) {
911
					tbl.style.opacity = 1;
912
913
					if (errorBrowse !== 0) {
914
						errorDialog(errorBrowse);
915
						return;
916
					}
917
918
					showFiles();
919
				});
920
			};
921
		}
922
923
		cell = row.insertCell(-1);
0 ignored issues
show
Unused Code introduced by
The assignment to variable cell seems to be never used. Consider removing it.
Loading history...
924
	}
925
}
926
927
function addAccountToTable(i) {
928
	if (ae.getOwnUid() === ae.admin_getUserUid(i)) return;
929
930
	const row = document.getElementById("tbd_accs").insertRow(-1);
931
	let cell;
932
	cell = row.insertCell(-1); cell.textContent = ae.uidToName(ae.admin_getUserUid(i));
933
	cell = row.insertCell(-1); cell.textContent = Math.round(ae.admin_getUserKib(i) / 1024);
934
	cell = row.insertCell(-1); cell.textContent = ae.admin_getUserNrm(i);
935
	cell = row.insertCell(-1); cell.textContent = ae.admin_getUserShd(i);
936
937
	cell = row.insertCell(-1);
938
	let btn = document.createElement("button");
939
	btn.type = "button";
940
	btn.textContent = "+";
941
	btn.disabled = (ae.admin_getUserLvl(i) === 3);
942
	btn.onclick = function() {const c = this.parentElement.parentElement.cells; adjustLevel(ae.admin_getUserUid(i), ae.admin_getUserLvl(i) + 1, c);};
943
	cell.appendChild(btn);
944
945
	cell = row.insertCell(-1); cell.textContent = ae.admin_getUserLvl(i);
946
947
	cell = row.insertCell(-1);
948
	btn = document.createElement("button");
949
	btn.type = "button";
950
	btn.textContent = "−";
951
	btn.disabled = (ae.admin_getUserLvl(i) === 0);
952
	btn.onclick = function() {const c = this.parentElement.parentElement.cells; adjustLevel(ae.admin_getUserUid(i), ae.admin_getUserLvl(i) - 1, c);};
953
	cell.appendChild(btn);
954
955
	cell = row.insertCell(-1);
956
	btn = document.createElement("button");
957
	btn.type = "button";
958
	btn.textContent = "X";
959
	btn.onclick = function() {
960
		const tr = this.parentElement.parentElement;
961
		ae.Account_Delete(ae.admin_getUserUid(i), function(error) {
962
			if (error === 0) tr.remove(); else errorDialog(error);
963
		});
964
	};
965
	cell.appendChild(btn);
966
}
967
968
function updateLimits() {
969
	const tbl = document.querySelector("#tbl_limits > tbody");
970
971
	if (ae.isUserAdmin()) {
972
		for (let i = 0; i < 4; i++) {
973
			tbl.rows[i].cells[1].children[0].value = ae.getLimitStorage(i);
974
			tbl.rows[i].cells[2].children[0].value = ae.getLimitNormalA(i);
975
			tbl.rows[i].cells[3].children[0].value = ae.getLimitShieldA(i);
976
		}
977
	} else {
978
		const lvl = ae.getOwnLevel();
979
		tbl.rows[lvl].cells[1].children[0].value = ae.getLimitStorage(lvl);
980
		tbl.rows[lvl].cells[2].children[0].value = ae.getLimitNormalA(lvl);
981
		tbl.rows[lvl].cells[3].children[0].value = ae.getLimitShieldA(lvl);
982
	}
983
}
984
985
function deleteAddress(addr) {
986
	const buttons = document.querySelectorAll("#tbl_addrs button");
987
	buttons.forEach(function(btn) {btn.disabled = true;});
988
989
	let addressToDelete = -1;
990
	for (let i = 0; i < ae.getAddressCount(); i++) {
991
		if (addr === ae.getAddress(i)) {
992
			addressToDelete = i;
993
			break;
994
		}
995
	}
996
997
	if (addressToDelete === -1) return;
998
999
	ae.Address_Delete(addressToDelete, function(error1) {
1000
		if (error1 !== 0) {
1001
			buttons.forEach(function(btn) {btn.disabled = false;});
1002
			errorDialog(error1);
1003
			return;
1004
		}
1005
1006
		document.getElementById("tbl_addrs").deleteRow(addressToDelete);
1007
		document.getElementById("write_from").remove(addressToDelete);
1008
1009
		const askList = document.getElementById("getask_addr");
1010
		for (let i = 0; i < askList.children.length; i++) {
1011
			if (askList.children[i].value === addr) {
1012
				askList.remove(i);
1013
				break;
1014
			}
1015
		}
1016
1017
		updateAddressCounts();
1018
1019
		ae.Private_Update(function(error2) {
1020
			buttons.forEach(function(btn) {btn.disabled = false;});
1021
			if (error2) errorDialog(error2);
1022
		});
1023
	});
1024
}
1025
1026
function setTab(isHistory, tabNum, pageNum) {
1027
	tab = tabNum;
1028
	if (pageNum !== -1) tabs[tab].cur = pageNum;
1029
1030
	document.querySelectorAll("#main1 > nav:first-of-type > button").forEach(function(btn, i) {
1031
		document.querySelectorAll("#main1 > .mid > div")[i].hidden = (tab !== i);
1032
		btn.disabled = (tab === i);
1033
	});
1034
1035
	const bigScreen = window.matchMedia("(min-width: 80em)").matches;
1036
	document.getElementById("main2").hidden = !bigScreen;
1037
	document.getElementById("btn_leave").disabled = bigScreen;
1038
1039
	switch (tab) {
1040
		case TAB_INBOX: showInbox(); break;
1041
		case TAB_DRBOX: showDrbox(); break;
1042
1043
		case TAB_WRITE:
1044
			if (tabs[tab].cur === 0) {
1045
				document.getElementById("div_write_1").hidden = false;
1046
				document.getElementById("div_write_2").hidden = true;
1047
				document.getElementById("write_recv").focus();
1048
			} else if (!writeVerify()) {
1049
				tabs[TAB_WRITE].cur = 0;
1050
				return;
1051
			}
1052
		break;
1053
1054
		case TAB_NOTES:
1055
			if (vaultPage === -2) {
1056
				vaultPage = -1;
1057
1058
				vault.downloadIndex(function(err) {
1059
					if (err === 0) {
1060
						vaultPage = 0;
1061
					}
1062
				});
1063
			}
1064
1065
			switch (tabs[tab].cur) {
1066
				case 0:
1067
					document.getElementById("div_notes").children[0].hidden = false;
1068
					document.getElementById("div_notes").children[1].hidden = true;
1069
					document.getElementById("div_notes").children[2].hidden = true;
1070
				break;
1071
1072
				case 1:
1073
					document.getElementById("div_notes").children[0].hidden = true;
1074
					document.getElementById("div_notes").children[1].hidden = false;
1075
					document.getElementById("div_notes").children[2].hidden = true;
1076
1077
					document.querySelector("#div_notepad meter").value = ae.getPrivateExtraSpace() / ae.getPrivateExtraSpaceMax();
1078
				break;
1079
1080
				case 2:
1081
					document.getElementById("div_notes").children[0].hidden = true;
1082
					document.getElementById("div_notes").children[1].hidden = true;
1083
					document.getElementById("div_notes").children[2].hidden = false;
0 ignored issues
show
introduced by
This node falls through to the next case due to this statement. Please add a comment either directly below this line or between the cases to explain.
Loading history...
1084
1085
				default:
1086
					showFiles();
1087
			}
1088
		break;
1089
1090
		case TAB_TOOLS:
1091
			for (let i = 0; i <= tabs[tab].max; i++) {
1092
				document.getElementById("div_tools").children[i].hidden = (i !== tabs[tab].cur);
1093
			}
1094
		break;
1095
	}
1096
1097
	document.getElementById("btn_dele").disabled = !tabs[tab].btnDele;
1098
	document.getElementById("btn_left").disabled = (tabs[tab].cur === 0);
1099
	document.getElementById("btn_rght").disabled = (tabs[tab].cur === tabs[tab].max);
1100
	document.getElementById("btn_updt").disabled = !tabs[tab].btnUpdt;
1101
1102
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
1103
}
1104
1105
window.onresize = function() {
1106
	setTab(true, tab, tabs[tab].cur);
1107
}
1108
1109
function clearWrite() {
1110
	setTab(false, TAB_WRITE, 0);
1111
1112
	document.querySelector("#write2_ask > input").value = "";
1113
	document.getElementById("write_body").value = "";
1114
	document.getElementById("write_subj").value = "";
1115
	document.getElementById("write_subj").readOnly = false;
1116
	document.getElementById("write_subj").setAttribute("data-replyid", "");
1117
	document.getElementById("write_recv").value = "";
1118
	document.getElementById("write_recv").readOnly = false;
1119
	document.getElementById("write_recv").focus();
1120
}
1121
1122
function refreshContactList() {
1123
	let opts = [];
1124
1125
	for (let i = 0; i < ae.getContactCount(); i++) {
1126
		const el = document.createElement("option");
1127
		el.value = ae.getContactMail(i);
1128
		opts.push(el);
1129
	}
1130
1131
	if (ae.isUserAdmin()) {
1132
		const el = document.createElement("option");
1133
		el.value = "public";
1134
		opts.push(el);
1135
	}
1136
1137
	document.getElementById("contact_emails").replaceChildren(...opts);
1138
}
1139
1140
function addContact(mail, name, note) {
1141
	const tbl = document.getElementById("tbl_ctact");
1142
	const row = tbl.insertRow(-1);
1143
1144
	let cell = row.insertCell(-1);
1145
	cell.autocapitalize = "off";
1146
	cell.contentEditable = true;
1147
	cell.inputMode = "email";
1148
	cell.spellcheck = false;
1149
	cell.textContent = mail;
1150
1151
	cell = row.insertCell(-1);
1152
	cell.autocapitalize = "words";
1153
	cell.contentEditable = true;
1154
	cell.spellcheck = false;
1155
	cell.textContent = name;
1156
1157
	cell = row.insertCell(-1);
1158
	cell.autocapitalize = "off";
1159
	cell.contentEditable = true;
1160
	cell.spellcheck = false;
1161
	cell.textContent = note;
1162
1163
	cell = row.insertCell(-1);
1164
	const el = document.createElement("button");
1165
	el.type = "button";
1166
	el.textContent = "X";
1167
	el.onclick = function() {row.remove();};
1168
	cell.appendChild(el);
1169
}
1170
1171
function addContacts() {
1172
	for (let i = 0; i < ae.getContactCount(); i++) {
1173
		addContact(
1174
			ae.getContactMail(i),
1175
			ae.getContactName(i),
1176
			ae.getContactNote(i)
1177
		);
1178
	}
1179
1180
	refreshContactList();
1181
}
1182
1183
function addAddress(num) {
1184
	const addrTable = document.getElementById("tbl_addrs");
1185
	const row = addrTable.insertRow(-1);
1186
	const addr = ae.getAddress(num);
1187
1188
	let pref = "";
1189
	let counter = 0;
1190
	for (let i = 0; i < ae.getAddressNick(num).length; i++) {
1191
		if (
1192
		    addr[counter] === ae.getAddressNick(num)[i].toLowerCase()
1193
		|| (addr[counter] === '0' && ae.getAddressNick(num)[i].toLowerCase() == 'o')
1194
		|| (addr[counter] === '1' && (ae.getAddressNick(num)[i].toLowerCase() == 'i' || ae.getAddressNick(num)[i].toLowerCase() == 'l'))
1195
		|| (addr[counter] === 'w' && ae.getAddressNick(num)[i].toLowerCase() == 'v')
1196
		) {
1197
			pref += ae.getAddressNick(num)[i].toLowerCase();
1198
			counter++;
1199
		}
1200
	}
1201
	pref += addr.slice(counter);
1202
1203
	let cell = row.insertCell(-1);
1204
	let el = document.createElement("input");
1205
	el.type = "text";
1206
	el.size = ae.isAddressShield(num) ? 16 : 15;
1207
1208
	if (document.getElementById("chk_addr_nick").checked) {
1209
		el.minLength = ae.getAddress(num).length;
1210
		el.maxLength = 31;
1211
		el.placeholder = ae.getAddress(num);
1212
		el.value = ae.getAddressNick(num);
1213
1214
		el.onchange = function() {
1215
			ae.setAddressNick(num, this.value);
1216
		};
1217
	} else {
1218
		el.value = pref;
1219
		el.readOnly = true;
1220
1221
		el.onclick = function() {
1222
			navigator.clipboard.writeText((ae.isAddressShield(num)? ae.shieldMix(el.value, 0) : pref) + "@" + ae.getDomainEml());
1223
		};
1224
	}
1225
1226
	cell.appendChild(el);
1227
1228
	cell = row.insertCell(-1);
1229
	el = document.createElement("input");
1230
	el.type = "checkbox";
1231
	el.checked = ae.getAddressAccInt(num);
1232
	cell.appendChild(el);
1233
1234
	cell = row.insertCell(-1);
1235
	el = document.createElement("input");
1236
	el.type = "checkbox";
1237
	el.checked = ae.getAddressAccExt(num);
1238
	cell.appendChild(el);
1239
1240
	cell = row.insertCell(-1);
1241
	el = document.createElement("input");
1242
	el.type = "checkbox";
1243
	el.checked = ae.getAddressAllVer(num);
1244
	cell.appendChild(el);
1245
1246
	cell = row.insertCell(-1);
1247
	el = document.createElement("input");
1248
	el.type = "checkbox";
1249
	el.checked = ae.getAddressAttach(num);
1250
	cell.appendChild(el);
1251
1252
	cell = row.insertCell(-1);
1253
	el = document.createElement("input");
1254
	el.type = "checkbox";
1255
	el.checked = ae.getAddressSecure(num);
1256
	cell.appendChild(el);
1257
1258
	cell = row.insertCell(-1);
1259
	el = document.createElement("input");
1260
	el.type = "checkbox";
1261
	el.checked = ae.getAddressOrigin(num);
1262
	cell.appendChild(el);
1263
1264
	cell = row.insertCell(-1);
1265
	el = document.createElement("button");
1266
	el.type = "button";
1267
	el.textContent = "X";
1268
	el.onclick = function() {deleteAddress(addr);};
1269
	cell.appendChild(el);
1270
1271
	el = document.createElement("option");
1272
	el.value = pref;
1273
	el.textContent = pref + "@" + ae.getDomainEml();
1274
	document.getElementById("write_from").appendChild(el);
1275
1276
	el = document.createElement("option");
1277
	el.value = addr;
1278
	el.textContent = addr;
1279
	document.getElementById("getask_addr").appendChild(el);
1280
}
1281
1282
function addAddresses() {
1283
	const si = Math.max(0, document.getElementById("write_from").selectedIndex);
1284
1285
	document.getElementById("tbl_addrs").replaceChildren();
1286
	document.getElementById("getask_addr").replaceChildren();
1287
	document.getElementById("write_from").replaceChildren();
1288
1289
	for (let i = 0; i < ae.getAddressCount(); i++) {
1290
		addAddress(i);
1291
	}
1292
1293
	document.getElementById("write_from").selectedIndex = si;
1294
}
1295
1296
function addressCreate(addr) {
1297
	document.getElementById("btn_address_create_normal").disabled = true;
1298
	document.getElementById("btn_address_create_shield").disabled = true;
1299
1300
	ae.Address_Create(addr, function(error1) {
1301
		if (error1 !== 0) {
1302
			updateAddressButtons();
1303
			errorDialog(error1, (addr !== "SHIELD") ? document.getElementById("txt_address_create_normal") : null);
1304
			return;
1305
		}
1306
1307
		ae.Private_Update(function(error2) {
1308
			updateAddressCounts();
1309
1310
			addAddress(ae.getAddressCount() - 1);
1311
			if (addr !== "SHIELD") {
1312
				document.getElementById("txt_address_create_normal").value = "";
1313
				document.getElementById("txt_address_create_normal").focus();
1314
			}
1315
1316
			if (error2 !== 0) errorDialog(error2, (addr !== "SHIELD") ? document.getElementById("txt_address_create_normal") : null);
1317
		});
1318
	});
1319
}
1320
1321
function reloadAccount() {
1322
	updateLimits();
1323
	addOwnAccount();
1324
	addContacts();
1325
	addAddresses();
1326
	updateAddressCounts();
1327
1328
	document.getElementById("fs_admin").disabled = !ae.isUserAdmin();
1329
	document.getElementById("txt_notepad").value = ae.getPrivateExtra();
1330
}
1331
1332
function writeVerify() {
1333
	if (
1334
	   !document.getElementById("write_recv").reportValidity()
1335
	|| !document.getElementById("write_subj").reportValidity()
1336
	|| !document.getElementById("write_body").reportValidity()
1337
	) return false;
1338
1339
	document.getElementById("div_write_1").hidden = true;
1340
	document.getElementById("div_write_2").hidden = false;
1341
1342
	document.getElementById("write2_recv").textContent = document.getElementById("write_recv").value;
1343
	document.getElementById("write2_subj").textContent = document.getElementById("write_subj").value;
1344
	document.getElementById("write2_rply").textContent = document.getElementById("write_subj").getAttribute("data-replyid");
1345
	document.getElementById("write2_body").textContent = document.getElementById("write_body").value;
1346
1347
	if (document.getElementById("write_recv").value.indexOf("@") >= 0) {
1348
		document.getElementById("write2_from").textContent = document.getElementById("write_from").value + "@" + ae.getDomainEml();
1349
		document.getElementById("write2_ask").hidden = true;
1350
	} else {
1351
		document.getElementById("write2_from").textContent = document.getElementById("write_from").value;
1352
		document.getElementById("write2_ask").hidden = (document.getElementById("write_recv").value === "public");
1353
	}
1354
1355
	document.querySelector("#write2_send > button").disabled = false;
1356
	document.getElementById("write2_btntxt").textContent = (document.getElementById("write_recv").value === "public") ? "Make" : "Send to";
1357
	return true;
1358
}
1359
1360
// Interface elements
1361
if (window.matchMedia("(prefers-color-scheme: light)").matches) document.querySelector("head > meta[name='theme-color']").content = "#eef";
1362
window.matchMedia("(prefers-color-scheme: light)").onchange = function() {document.querySelector("head > meta[name='theme-color']").content = window.matchMedia("(prefers-color-scheme: light)").matches? "#eef" : "#001";};
1363
1364
window.onpopstate = function(event) {
1365
	if (!isReady || !event.state) return;
1366
	setTab(true, event.state.tab, event.state.page);
1367
	msgDisplay = event.state.msg;
1368
1369
	if (msgDisplay) {
1370
		switch (msgDisplay.type) {
1371
			case "ext": displayMsg(true, false, msgDisplay.num); break;
1372
			case "int": displayMsg(true, true, msgDisplay.num); break;
1373
			case "out": displayOutMsg(true, msgDisplay.num); break;
1374
			case "upl": displayFile(true, msgDisplay.num, null); break;
1375
			case "ext_exp": displayExport(true, false, msgDisplay.num); break;
1376
			case "int_exp": displayExport(true, true, msgDisplay.num); break;
1377
		}
1378
	}
1379
};
1380
1381
document.querySelectorAll("#main1 > nav:first-of-type > button").forEach(function(btn, i) {
1382
	btn.onclick = function() {setTab(false, i, -1);};
1383
});
1384
1385
document.getElementById("btn_left").onclick = function() {
1386
	setTab(false, tab, tabs[tab].cur - 1);
1387
};
1388
1389
document.getElementById("btn_rght").onclick = function() {
1390
	setTab(false, tab, tabs[tab].cur + 1);
1391
};
1392
1393
document.getElementById("btn_dele").onclick = function() {
1394
	this.blur();
1395
1396
	if (tab === TAB_WRITE) clearWrite();
1397
};
1398
1399
document.getElementById("btn_updt").onclick = function() {
1400
	const btn = this;
1401
	btn.disabled = true;
1402
	btn.blur();
1403
1404
	if (tab === TAB_INBOX) {
1405
		document.getElementById("tbl_inbox").style.opacity = 0.5;
1406
1407
		ae.Message_Browse(true, false, function(error) {
1408
			btn.disabled = false;
1409
			document.getElementById("tbl_inbox").style.opacity = 1;
1410
1411
			if (error === 0) {
1412
				showInbox();
1413
			} else {
1414
				errorDialog(error);
1415
			}
1416
		});
1417
	}
1418
};
1419
1420
document.getElementById("btn_mdele").onclick = function() {
1421
	const delId = document.querySelector("article").getAttribute("data-msgid");
1422
	if (!delId) return;
1423
1424
	const btn = this;
1425
	btn.blur();
1426
	btn.disabled = true;
1427
1428
	ae.Message_Delete(delId, function(error) {
1429
		if (error !== 0) {
1430
			btn.disabled = false;
1431
			errorDialog(error);
1432
			return;
1433
		}
1434
1435
		switch (tab) {
1436
			case TAB_INBOX: showInbox(); break;
1437
			case TAB_DRBOX: showDrbox(); break;
1438
			case TAB_NOTES: showFiles(); break;
1439
		}
1440
	});
1441
};
1442
1443
document.getElementById("btn_leave").onclick = function() {
1444
	document.getElementById("main2").hidden = true;
1445
	document.getElementById("main1").hidden = false;
1446
};
1447
1448
document.getElementById("btn_newcontact").onclick = function() {
1449
	addContact("", "", "");
1450
};
1451
1452
document.getElementById("btn_savecontacts").onclick = function() {
1453
	while (ae.getContactCount() > 0) {
1454
		ae.deleteContact(0);
1455
	}
1456
1457
	for (const row of document.getElementById("tbl_ctact").rows) {
1458
		ae.addContact(row.cells[0].textContent, row.cells[1].textContent, row.cells[2].textContent);
1459
	}
1460
1461
	refreshContactList();
1462
1463
	const btn = this;
1464
	btn.disabled = true;
1465
1466
	ae.Private_Update(function(error) {
1467
		btn.disabled = false;
1468
		if (error) errorDialog(error);
1469
	});
1470
};
1471
1472
document.getElementById("chk_addr_nick").onclick = function() {
1473
	addAddresses();
1474
};
1475
1476
document.getElementById("btn_address_create_normal").onclick = function() {
1477
	if (ae.getAddressCountNormal() >= ae.getLimitNormalA(ae.getOwnLevel()) || ae.getAddressCountNormal() + ae.getAddressCountShield() >= 31) return;
1478
1479
	const txtNewAddr = document.getElementById("txt_address_create_normal");
1480
	if (!txtNewAddr.reportValidity()) return;
1481
1482
	addressCreate(txtNewAddr.value.toLowerCase());
1483
};
1484
1485
document.getElementById("txt_address_create_normal").onkeyup = function(event) {
1486
	if (event.key !== "Enter") return;
1487
	event.preventDefault();
1488
	document.getElementById("btn_address_create_normal").click();
1489
};
1490
1491
document.getElementById("btn_address_create_shield").onclick = function() {
1492
	if (ae.getAddressCountShield() >= ae.getLimitShieldA(ae.getOwnLevel()) || ae.getAddressCountNormal() + ae.getAddressCountShield() >= 31) return;
1493
1494
	addressCreate("SHIELD");
1495
};
1496
1497
document.getElementById("btn_address_update").onclick = function() {
1498
	const btn = this;
1499
	btn.disabled = true;
1500
1501
	const rows = document.getElementById("tbl_addrs").rows;
1502
1503
	for (let i = 0; i < rows.length; i++) {
1504
		ae.setAddressAccInt(i, rows[i].getElementsByTagName("input")[1].checked);
1505
		ae.setAddressAccExt(i, rows[i].getElementsByTagName("input")[2].checked);
1506
		ae.setAddressAllVer(i, rows[i].getElementsByTagName("input")[3].checked);
1507
		ae.setAddressAttach(i, rows[i].getElementsByTagName("input")[4].checked);
1508
		ae.setAddressSecure(i, rows[i].getElementsByTagName("input")[5].checked);
1509
		ae.setAddressOrigin(i, rows[i].getElementsByTagName("input")[6].checked);
1510
	}
1511
1512
	ae.Address_Update(function(error) {
1513
		btn.disabled = false;
1514
		if (error) errorDialog(error);
1515
	});
1516
};
1517
1518
1519
document.getElementById("txt_sender").onkeyup = function(event) {
1520
	if (event.key !== "Enter") return;
1521
	event.preventDefault();
1522
	document.getElementById("btn_sender").click();
1523
};
1524
1525
document.getElementById("btn_reg").onclick = function() {
1526
	const btn = document.getElementById("btn_reg");
1527
	const uak = document.getElementById("txt_reg_uak");
1528
	const epk = document.getElementById("txt_reg_epk");
1529
1530
	if (!uak.reportValidity() || !epk.reportValidity()) return;
1531
	btn.disabled = true;
1532
	uak.disabled = true;
1533
	epk.disabled = true;
1534
1535
	ae.Account_Create(uak.value, epk.value, function(error) {
1536
		if (error === 0) {
1537
			addAccountToTable(ae.admin_getUserCount() - 1);
1538
			uak.value = "";
1539
			epk.value = "";
1540
		} else errorDialog(error);
1541
1542
		btn.disabled = false;
1543
		uak.disabled = false;
1544
		epk.disabled = false;
1545
	});
1546
};
1547
1548
document.getElementById("chk_dng_usr").onclick = function() {
1549
	document.getElementById("btn_lowme").disabled = !this.checked || (ae.getOwnLevel() === 0);
1550
	document.getElementById("btn_erame").disabled = !this.checked;
1551
	document.getElementById("btn_delme").disabled = !this.checked;
1552
};
1553
1554
document.getElementById("btn_erame").onclick = function() {
1555
	ae.Message_Delete("ALL", function(error) {
1556
		if (error === 0) {
1557
			document.getElementById("chk_dng_usr").checked = false;
1558
			document.getElementById("chk_dng_usr").onclick();
1559
		} else errorDialog(error);
1560
	});
1561
};
1562
1563
document.getElementById("btn_notepad_restore").onclick = function() {
1564
	document.getElementById("txt_notepad").value = ae.getPrivateExtra();
1565
	document.getElementById("btn_notepad_savepad").disabled = true;
1566
	document.getElementById("txt_notepad").oninput = function() {
1567
		this.oninput = null;
1568
		document.getElementById("btn_notepad_savepad").disabled = false;
1569
		document.getElementById("btn_notepad_savepad").textContent = "Save";
1570
	};
1571
};
1572
1573
document.getElementById("txt_notepad").oninput = function() {
1574
	document.getElementById("btn_notepad_savepad").disabled = false;
1575
};
1576
1577
document.getElementById("btn_notepad_savepad").onclick = function() {
1578
	const btn = this;
1579
	btn.disabled = true;
1580
1581
	const error = ae.setPrivateExtra(document.getElementById("txt_notepad").value);
1582
	if (error !== 0) {
1583
		btn.disabled = false;
1584
		errorDialog(error);
1585
		return;
1586
	}
1587
1588
	ae.Private_Update(function(error2) {
1589
		if (error2 !== 0) {
1590
			btn.disabled = false;
1591
			errorDialog(error2);
1592
		} else {
1593
			document.querySelector("#div_notepad meter").value = ae.getPrivateExtraSpace() / ae.getPrivateExtraSpaceMax();
1594
			btn.textContent = "Saved";
1595
			document.getElementById("txt_notepad").oninput = function() {
1596
				this.oninput = null;
1597
				btn.textContent = "Save";
1598
				btn.disabled = false;
1599
			};
1600
		}
1601
	});
1602
};
1603
1604
document.getElementById("btn_notepad_saveupl").onclick = function() {
1605
	const np = document.getElementById("txt_notepad");
1606
	np.disabled = true;
1607
1608
	let fname = prompt("Save as...", "Untitled");
0 ignored issues
show
Debugging Code Best Practice introduced by
The prompt UI element is often considered obtrusive and is generally only used as a temporary measure. Consider replacing it with another UI element.
Loading history...
1609
	if (!fname.endsWith(".txt")) fname += ".txt";
1610
1611
	ae.Message_Upload(fname, np.value, function(error) {
1612
		if (error === 0) {
1613
			np.value = "";
1614
			showFiles();
1615
			document.getElementById("tbd_accs").children[0].children[1].textContent = Math.round(ae.getTotalMsgBytes() / 1024 / 1024);
1616
		} else errorDialog(error);
1617
1618
		np.disabled = false;
1619
	});
1620
};
1621
1622
document.getElementById("btn_upload").onclick = function() {
1623
	const btn = this;
1624
	const fileSelector = document.createElement("input");
1625
	fileSelector.type = "file";
1626
	fileSelector.click();
1627
1628
	fileSelector.onchange = function() {
1629
		btn.disabled = true;
1630
1631
		const reader = new FileReader();
1632
		reader.onload = function() {
1633
			ae.Message_Upload(fileSelector.files[0].name, new Uint8Array(reader.result), function(error) {
1634
				if (error === 0) {
1635
					showFiles();
1636
					document.getElementById("tbd_accs").children[0].children[1].textContent = Math.round(ae.getTotalMsgBytes() / 1024 / 1024);
1637
				} else errorDialog(error);
1638
1639
				btn.disabled = false;
1640
			});
1641
		};
1642
1643
		reader.readAsArrayBuffer(fileSelector.files[0]);
1644
	};
1645
};
1646
1647
document.getElementById("btn_pg").onclick = function() {
1648
//	localStorage.greeting = document.getElementById("txt_pg").value;
1649
};
1650
1651
document.querySelector("#write2_send > button").onclick = function() {
1652
	const btn = this;
1653
	btn.disabled = true;
1654
1655
	// Public announcement
1656
	if (document.getElementById("write2_recv").textContent === "public") {
1657
		ae.Message_Public(document.getElementById("write_subj").value, document.getElementById("write_body").value, function(error) {
1658
			if (error !== 0) {
1659
				document.getElementById("write2_btntxt").textContent = "Retry making";
1660
				btn.disabled = false;
1661
				errorDialog(error);
1662
				return;
1663
			}
1664
1665
			clearWrite();
1666
			displayMsg(false, true, 0);
1667
		});
1668
1669
		return;
1670
	}
1671
1672
	// Email or internal message
1673
	let ask = null;
1674
	if (document.getElementById("write2_recv").textContent.indexOf("@") === -1) {
1675
		const elAsk = document.querySelector("#write2_ask > input");
1676
		if (!elAsk.reportValidity()) {
1677
			btn.disabled = false;
1678
			return;
1679
		}
1680
		ask = elAsk.value;
1681
	}
1682
1683
	document.getElementById("write2_btntxt").textContent = "Sending to";
1684
1685
	ae.Message_Create(
1686
		document.getElementById("write_subj").value,
1687
		document.getElementById("write_body").value,
1688
		document.getElementById("write_from").value,
1689
		document.getElementById("write_recv").value,
1690
		document.getElementById("write_subj").getAttribute("data-replyid"),
1691
		ask,
1692
		function(error) {
1693
			if (error !== 0) {
1694
				errorDialog(error);
1695
				document.getElementById("write2_btntxt").textContent = "Retry sending to";
1696
				btn.disabled = false;
1697
				return;
1698
			}
1699
1700
			showDrbox();
1701
			clearWrite();
1702
			displayOutMsg(false, 0);
1703
		}
1704
	);
1705
};
1706
1707
document.getElementById("btn_sender").onclick = function() {
1708
	ae.Message_Sender(document.getElementById("txt_sender_hash").value, Date.parse(document.getElementById("txt_sender_date").value) / 1000, function(error, result) {
1709
		if (error !== 0) {
1710
			errorDialog(error);
1711
			return;
1712
		}
1713
1714
		document.getElementById("txt_sender_res").value = result;
1715
	});
1716
};
1717
1718
document.getElementById("btn_limits").onclick = function() {
1719
	const btn = this;
1720
	btn.disabled = true;
1721
1722
	const mib = [parseInt(document.getElementById("lim_mib0").value, 10), parseInt(document.getElementById("lim_mib1").value, 10), parseInt(document.getElementById("lim_mib2").value, 10), parseInt(document.getElementById("lim_mib3").value, 10)];
1723
	const nrm = [parseInt(document.getElementById("lim_nrm0").value, 10), parseInt(document.getElementById("lim_nrm1").value, 10), parseInt(document.getElementById("lim_nrm2").value, 10), parseInt(document.getElementById("lim_nrm3").value, 10)];
1724
	const shd = [parseInt(document.getElementById("lim_shd0").value, 10), parseInt(document.getElementById("lim_shd1").value, 10), parseInt(document.getElementById("lim_shd2").value, 10), parseInt(document.getElementById("lim_shd3").value, 10)];
1725
1726
	ae.Setting_Limits(mib, nrm, shd, function(error) {
1727
		btn.disabled = false;
1728
1729
		if (error !== 0) {
1730
			errorDialog(error);
1731
		} else {
1732
			updateAddressCounts();
1733
		}
1734
	});
1735
};
1736
1737
document.getElementById("getask_addr").onchange = function() {
1738
	document.getElementById("getask_result").textContent = ae.getOwnAsk(document.getElementById("getask_addr").value);
1739
};
1740
1741
document.getElementById("txt_umk").onfocus = function() {
1742
//	document.getElementById("greeting").textContent = localStorage.greeting;
1743
};
1744
1745
document.getElementById("txt_umk").onkeyup = function(event) {
1746
	if (event.key !== "Enter") return;
1747
	event.preventDefault();
1748
	document.getElementById("btn_enter").click();
1749
};
1750
1751
document.getElementById("btn_enter").onclick = function() {
1752
	const txtUmk = document.getElementById("txt_umk");
1753
1754
	if (txtUmk.value === "") {
1755
		ae.reset();
1756
		document.getElementById("greeting").textContent = "Data cleared";
1757
		return;
1758
	}
1759
1760
	if (!txtUmk.reportValidity()) return;
1761
1762
	const btn = this;
1763
	btn.disabled = true;
1764
1765
	document.getElementById("txt_umk").disabled = true;
1766
1767
	ae.setKeys(txtUmk.value, function(successSetKeys) {
1768
		if (!successSetKeys) {
1769
			document.getElementById("txt_umk").disabled = false;
1770
			txtUmk.focus();
1771
1772
			document.getElementById("greeting").textContent = "SetKeys failed";
1773
			btn.disabled = false;
1774
			return;
1775
		}
1776
1777
		document.body.style.cursor = "wait";
1778
		document.getElementById("greeting").textContent = "Connecting...";
1779
1780
		if (vaultPage === -3) {
1781
			vault.setKeys(txtUmk.value, function(vaultKeysOk) {
1782
				if (vaultKeysOk) vaultPage = -2;
1783
			});
1784
		}
1785
1786
		ae.Message_Browse(true, true, function(errorBrowse) {
1787
			document.body.style.cursor = "";
1788
1789
			if (errorBrowse !== 0 && errorBrowse !== 0x09) {
1790
				let errorMsg = ae.getErrorMessage(errorBrowse);
1791
				if (typeof(errorMsg) == "object") errorMsg = errorMsg[1];
1792
1793
				document.getElementById("greeting").textContent = errorMsg + " ("+ ((errorBrowse >= 400) ? errorBrowse : "0x" + errorBrowse.toString(16).padStart(2, "0").toUpperCase()) + ")";
1794
				document.getElementById("txt_umk").disabled = false;
1795
				btn.disabled = false;
1796
				btn.focus();
1797
				return;
1798
			}
1799
1800
			txtUmk.value = "";
1801
			document.getElementById("div_begin").hidden = true;
1802
			document.getElementById("div_main").hidden = false;
1803
			isReady = true;
1804
			reloadAccount();
1805
			history.replaceState({tab: 0, page: 0, msg: msgDisplay}, null);
1806
			setTab(true, 0, 0);
1807
1808
			if (errorBrowse !== 0) errorDialog(errorBrowse);
1809
			if (!ae.isUserAdmin()) return;
1810
1811
			ae.Account_Browse(function(errorAcc) {
1812
				if (errorAcc === 0) {
1813
					for (let i = 0; i < ae.admin_getUserCount(); i++) {addAccountToTable(i);}
1814
					updateLimits();
1815
				} else {
1816
					errorDialog(errorAcc);
1817
				}
1818
			});
1819
		});
1820
	});
1821
};
1822
1823
});
1824